Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 09.04.2014, 16:54
Интересующийся
Отправить личное сообщение для FactoREAL Посмотреть профиль Найти все сообщения от FactoREAL
 
Регистрация: 09.04.2014
Сообщений: 14

XmlHttpRequest.send не корректно работает в Chrome
Здравствуйте. Пытаюсь реализовать передачу файлов (изображений) при помощи js на сервер (php скрипту). Реализую следующим образом (вкратце):
файл у клиента выбирается при помощи
<input type="file" multiple="true">

затем он считывается при помощи
$("input[type=file]").change(function(){
	var f = $(this)[0].files;
	displayFiles(f);
});

function displayFiles(files) {
...
var reader = new FileReader();
	reader.onload = (function(aImg) {
		return function(e) {
			aImg.attr('src', e.target.result);
		};
	})(li.imgbox.img);
	reader.readAsDataURL(file);
}

потом, при клике на кнопку все выбранные файлы загружаются на сервер
xhr = new XMLHttpRequest();
reader = new FileReader();
...
reader.onload = function() {
 xhr.open("POST", params.url);
 var boundary = "xxxxxxxxx";
 xhr.setRequestHeader("Content-Type", "multipart/form-data, boundary="+boundary);
 xhr.setRequestHeader("Cache-Control", "no-cache");

 var body = "--" + boundary + "\r\n";
 body += "Content-Disposition: form-data; name='"+(params.fieldName || 'file')+"'; filename='" + params.file.name + "'\r\n";
 body += "Content-Type: application/octet-stream\r\n\r\n";
 body += reader.result + "\r\n";
 body += "--" + boundary + "--";

 if(xhr.sendAsBinary) {
	// firefox
	xhr.sendAsBinary(body);
 } else {
	// chrome (W3C spec.)
	xhr.send(body);
 }
}
reader.readAsBinaryString(params.file);

на сервере пока что происходит простейший прием файла php скриптом:
$uploadedFile = "upload/".$_FILES['new_pic']['name'];
if(is_uploaded_file($_FILES['new_pic']['tmp_name'])) {
	if (move_uploaded_file($_FILES['new_pic']['tmp_name'], $uploadedFile)) {
		$data['success'] = "Удачно передано";
	} else {
		$file_error=true;
		$data['errors'] = "не удалось сохранить файл";
	}
}

проблема в том, что данная реализация прекрасно работает в браузере Firefox, но отказывается работать в Google Chrome. Если точнее, то в хроме загрузка файла на сервер в принципе происходит, но файл после этого становится большего объема чем исходный и нечитаймый. т.е. если исходный файл pic.jpg весил 1Мб, то после передачи, на сервере он весит уже 1,2Мб и не открывается на просмотр. Короче становится "битым". А так же в хроме почему-то не получается передать большие файлы (около 2Мб) - $_FILES['error'] возвращает 1 (превышен допустимый объем передаваемого файла). Хотя тот же самый файл прекрасно передается в браузере Firefox... Я так думаю что метод send() объекта XmlHttpRequest передает данные не корректно, т.к. метод sendAsBinary() в Firefox работает как надо.

Последний раз редактировалось FactoREAL, 09.04.2014 в 16:59.
Ответить с цитированием
  #2 (permalink)  
Старый 09.04.2014, 17:02
Отправить личное сообщение для Octane Посмотреть профиль Найти все сообщения от Octane  
Регистрация: 10.07.2008
Сообщений: 3,873

Попробуй вместо FileReader использовать FormData, чтобы не формировать тело запроса.
var xhr = new XMLHttpRequest,
	data = new FormData(здесь ссылка на элемент формы);
xhr.open("POST", params.url);
xhr.setRequestHeader("Content-Type", "multipart/form-data");
xhr.send(data);
Ответить с цитированием
  #3 (permalink)  
Старый 09.04.2014, 17:07
Интересующийся
Отправить личное сообщение для FactoREAL Посмотреть профиль Найти все сообщения от FactoREAL
 
Регистрация: 09.04.2014
Сообщений: 14

да дело в том, что файл "считывается" не напрямую из input'a, а предварительно они заносятся в объект (типа массив), а затем обрабатывается этот массив и каждый его элемент уже передается на отправку.
Ответить с цитированием
  #4 (permalink)  
Старый 09.04.2014, 17:10
Отправить личное сообщение для Octane Посмотреть профиль Найти все сообщения от Octane  
Регистрация: 10.07.2008
Сообщений: 3,873

может быть Content-Length еще надо указать или readAsBinary использовать, раз передается octet-stream

Последний раз редактировалось Octane, 09.04.2014 в 17:12.
Ответить с цитированием
  #5 (permalink)  
Старый 09.04.2014, 17:27
Интересующийся
Отправить личное сообщение для FactoREAL Посмотреть профиль Найти все сообщения от FactoREAL
 
Регистрация: 09.04.2014
Сообщений: 14

ну с Content-Length даже в firefox битые файлы получаются (надо будет выискивать "правильный" размер видимо), а по поводу readAsBinary не очень понял. я же его и так использую.
...	reader.readAsBinaryString(params.file);
Ответить с цитированием
  #6 (permalink)  
Старый 09.04.2014, 17:45
Отправить личное сообщение для Octane Посмотреть профиль Найти все сообщения от Octane  
Регистрация: 10.07.2008
Сообщений: 3,873

Сообщение от FactoREAL
а по поводу readAsBinary не очень понял. я же его и так использую
не внимательно посмотрел.

Не пробовал, но может прокатит создать FormData и методом append файлы добавлять?
Сообщение от MDN
void append(DOMString name, File value, optional DOMString filename);
void append(DOMString name, Blob value, optional DOMString filename);
Ответить с цитированием
  #7 (permalink)  
Старый 09.04.2014, 18:40
Интересующийся
Отправить личное сообщение для FactoREAL Посмотреть профиль Найти все сообщения от FactoREAL
 
Регистрация: 09.04.2014
Сообщений: 14

ну если вы имели ввиду именно readAsBinary, тогда я не понимаю о чем вы. ведь у XMLHttpRequest нет такого метода.
Ответить с цитированием
  #8 (permalink)  
Старый 09.04.2014, 21:31
Интересующийся
Отправить личное сообщение для FactoREAL Посмотреть профиль Найти все сообщения от FactoREAL
 
Регистрация: 09.04.2014
Сообщений: 14

ну и помучался я с этой загрузкой. в итоге удалось реализовать рабочий вариант, работает в firefox, chrome и opera, думаю в safari тоже должно(не проверял). Как и предлагали
Цитата:
создать FormData и методом append файлы добавлять
именно так и заработало правильно. ну и если кому будет интересно в будущем часть кода, отвечающая за отправку файла:
xhr = new XMLHttpRequest();
fd = new FormData();
...
function sendFile(file) {
	 xhr.open("POST", params.url);
	 fd.append("<file_field>", file);
	 xhr.send(fd);
}
sendFile(params.file);
Ответить с цитированием
  #9 (permalink)  
Старый 09.04.2014, 21:40
Отправить личное сообщение для Octane Посмотреть профиль Найти все сообщения от Octane  
Регистрация: 10.07.2008
Сообщений: 3,873

для IE лучше добавить xhr.setRequestHeader("Content-Type", "multipart/form-data"), а то иногда пустой запрос уходит
Ответить с цитированием
  #10 (permalink)  
Старый 18.04.2014, 15:25
Новичок на форуме
Отправить личное сообщение для colonel_337 Посмотреть профиль Найти все сообщения от colonel_337
 
Регистрация: 21.02.2013
Сообщений: 3

Два дня с этой проблемой ковырялся, с тем же скриптом. Пример выше не помог.
Корректно загружала картинки только мазилла, остальные браузеры били файлы, размер загруженного увеличивался, картинки не открывались.

Может кому поможет, решение простое:
.......
        body += "Content-Disposition: form-data; name='"+(params.fieldName || 'file')+"';filename='" + unescape( encodeURIComponent(params.file.name)) + "'\r\n";
        body += "Content-Type: application/octet-stream\r\n\r\n";
        body += self.reader.result + "\r\n";
        body += "--" + boundary + "--";

	
        if (!XMLHttpRequest.prototype.sendAsBinary) {
            XMLHttpRequest.prototype.sendAsBinary = function(datastr) {
                function byteValue(x) {
                    return x.charCodeAt(0) & 0xff;
                }
                var ords = Array.prototype.map.call(datastr, byteValue);
                var ui8a = new Uint8Array(ords);
                this.send(ui8a.buffer);
            }
        }



        if(self.xhr.sendAsBinary) {
           // firefox
            self.xhr.sendAsBinary(body);
        } else {
           // chrome (W3C spec.)
            self.xhr.send(body);
        }
.............
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
jQuery.get работает в FF и не работает в Chrome Варфаламей AJAX и COMET 2 27.01.2014 13:00
Работает только в Chrome vave Элементы интерфейса 4 08.11.2013 02:48
Не корректно работает slice Dotod Общие вопросы Javascript 20 30.01.2010 23:31
свойство innerHTML в Opera и Firefox работает не корректно? figaro Javascript под браузер 1 05.11.2009 00:57
Opera не корректно работает со скриптом Anat.nem Opera, Safari и др. 4 30.10.2009 13:39